Code
!pip install --quiet plotnine geopandas!pip install --quiet plotnine geopandas# If you prefer uploading directly:
from google.colab import files
import io, pandas as pd
uploaded = files.upload() # select your 'Unicef data for quarto.csv'
df = pd.read_csv(io.BytesIO(uploaded[next(iter(uploaded))]))
# Alternative: load from Drive
# from google.colab import drive
# drive.mount('/content/drive')
# df = pd.read_csv('/content/drive/MyDrive/path/to/Unicef data for quarto.csv')
import geopandas as gpd
from plotnine import *Saving Unicef data for quarto.csv to Unicef data for quarto (1).csv
Millions of girls aged 15–19 around the world face a big decision: stay in school or become young mothers. The adolescent birth rate — how many girls give birth per 1,000 — shows us how well a country supports its young women with education, health care, and opportunities. In this story, we’ll explore:
Where teen birth rates are highest in 2006?
Which ten countries have the worst rates?
How a country’s wealth relates to these rates?
How global rates have changed from 2000 to 2023?
Each scene will help us understand the challenges girls face and how we can use this information to help them stay healthy and in school.
# Cell 3 – Choropleth for YEAR (e.g. 2006)
import requests, pandas as pd
from plotnine import (
ggplot, aes, geom_polygon, coord_fixed,
scale_fill_gradient, labs, theme_void
)
# 1. Download & flatten the GeoJSON (same as before)
url = "https://raw.githubusercontent.com/datasets/geo-countries/master/data/countries.geojson"
geo = requests.get(url).json()
rows = []
for f in geo["features"]:
iso3 = f["properties"]["ISO3166-1-Alpha-3"]
polys = (f["geometry"]["coordinates"]
if f["geometry"]["type"] == "MultiPolygon"
else [f["geometry"]["coordinates"]])
for pi, poly in enumerate(polys):
for ci, (x, y) in enumerate(poly[0]):
rows.append({
"ISO3": iso3,
"poly_id": f"{iso3}_{pi}",
"coord_id":ci,
"x": x,
"y": y
})
map_df = pd.DataFrame(rows)
# 2. Pick a year with broad coverage
YEAR = 2006
# 3. Grab the teen‐birth rates for that year (use alpha_3_code_y)
dataY = (
df[df["Year"] == YEAR]
.rename(columns={
"alpha_3_code_y":"ISO3",
"obs_value": "teen_birth_rate"
})[["ISO3", "teen_birth_rate"]]
)
# 4. Merge & immediately re-sort by polygon & vertex
choropleth = (
map_df
.merge(dataY, on="ISO3", how="inner")
.sort_values(["poly_id", "coord_id"])
.reset_index(drop=True)
)
# 5. Drop any leftover NaNs (should be none with inner merge)
choropleth = choropleth.dropna(subset=["teen_birth_rate"])
# 6. Plot the map
(
ggplot()
+ geom_polygon(
data=choropleth,
mapping=aes(
x="x", y="y",
group="poly_id",
order="coord_id",
fill="teen_birth_rate"
),
color="black", size=0.1
)
+ coord_fixed(1.3)
+ scale_fill_gradient(
low="#f7fbff", high="#08306b",
name=f"Births per 1,000 women ({YEAR})"
)
+ labs(title=f"Adolescent Birth Rate by Country, {YEAR}")
+ theme_void()
)In 2006, a world map painted in gradients of blue reveals a stark truth: where adolescent birth rates soar above 80 births per 1,000 girls, life chances narrow dramatically. These darkest hues cluster in sub-Saharan Africa and remote island nations—places where poverty, limited schooling, and sparse health care combine to rob girls of childhood. In contrast, vast swaths of Europe, North America, and East Asia glow almost white, signaling rates below ten per 1,000.
Why it matters? Every shaded country on that map represents communities where girls are pulled from classrooms into motherhood—often perpetuating cycles of poverty, curtailing education, and endangering health.
from plotnine import (
ggplot, aes, geom_col, coord_flip,
labs, theme_minimal, scale_fill_hue, theme, element_text
)
(
ggplot(top10, aes(
x='reorder(Country, rate)',
y='rate',
fill='Country' # ← map fill to Country
))
+ geom_col()
+ coord_flip()
+ scale_fill_hue(name="Country") # ← use a qualitative hue scale
+ labs(
title="Top-10 Countries by Adolescent Birth Rate, 2006",
x="",
y="Births per 1,000 women"
)
+ theme_minimal()
+ theme(
legend_position = "right",
legend_text = element_text(size=8),
legend_key_size = 6
)
)
These ten nations, though diverse in culture and geography, share a painful commonality: adolescent girls there face some of the world’s highest risks of early pregnancy and its life-altering consequences. Each bar is not just a statistic but a spotlight on communities in urgent need of education, health services, and social support.
# Cell 5 – GDP per Capita vs. Adolescent Birth Rate for Top-10 Countries (2006)
import pandas as pd
from plotnine import (
ggplot, aes, geom_point, stat_smooth,
scale_x_log10, scale_y_continuous,
scale_color_hue, scale_size_continuous,
labs, theme_minimal, theme, element_text,
guides
)
# 1. Prepare the full 2006 slice
df2006 = (
df[df["Year"] == 2006]
.rename(columns={"obs_value": "rate"})
.dropna(subset=[
"GDP per capita (constant 2015 US$)",
"rate",
"Population, total"
])
)
df2006["pop_millions"] = df2006["Population, total"] / 1e6
# 2. Compute the Top-10 countries by rate
top10_countries = (
df2006.nlargest(10, "rate")["Country"]
.tolist()
)
# 3. Subset to those Top-10
df_top10 = df2006[df2006["Country"].isin(top10_countries)].copy()
# 4. Plot
(
ggplot(df_top10, aes(
x="GDP per capita (constant 2015 US$)",
y="rate",
color="Country",
size="pop_millions" # still driving point size
))
+ geom_point(alpha=0.8)
+ stat_smooth(
mapping=aes(
x="GDP per capita (constant 2015 US$)",
y="rate"
),
method="lm", color="black", se=False
)
+ scale_x_log10(
breaks=[300, 500, 1_000, 2_000, 5_000, 10_000],
labels=lambda br: [f"{int(round(x)):,}" for x in br]
)
+ scale_y_continuous(
breaks=range(0, 101, 20),
labels=[str(v) for v in range(0, 101, 20)]
)
+ scale_color_hue(name="Country")
+ scale_size_continuous(
range=(4, 12),
name="Population (M)"
)
+ guides(
size=False # ← drop the Population legend
)
+ labs(
title="Adolescent Birth Rate vs. GDP per Capita (2006)",
x="GDP per Capita",
y="Adolescent Birth Rate (per 1 000 women)"
)
+ theme_minimal()
+ theme(
axis_text_x = element_text(rotation=45, hjust=1),
legend_position = "right",
plot_title = element_text(size=14, margin={'b':10})
)
)
Does money buy safety? Generally, yes—GDP per capita and teen birth rates slide in opposite directions. Yet outliers like Vanuatu remind us that financial averages mask local realities. Bubble sizes—scaled by population—reveal that “low” rates in populous nations may still translate to millions of adolescent pregnancies.
import pandas as pd
from plotnine import (
ggplot, aes, geom_line, annotate,
scale_x_continuous, labs,
theme_minimal, theme, element_text
)
# 1. Global *unweighted* average
ts2 = (
df
.dropna(subset=["obs_value"])
.groupby("Year")["obs_value"]
.mean()
.loc[2000:2023]
.reset_index(name="avg_rate")
)
max_rate = ts2.avg_rate.max()
(
ggplot(ts2, aes("Year","avg_rate"))
+ annotate("rect",
xmin=2020, xmax=2021,
ymin=0, ymax=max_rate,
alpha=0.2, fill="lightblue")
+ geom_line(size=1.2, color="darkgreen")
+ annotate("text",
x=2020.5, y=max_rate*0.95,
label="COVID-19 period",
ha="center", va="top",
size=10)
+ scale_x_continuous(breaks=range(2000,2024,2))
+ labs(
title="Global Average Adolescent Birth Rate, 2000–2023",
x="Year",
y="Births per 1,000 girls aged 15–19 (country-average)"
)
+ theme_minimal()
+ theme(
axis_text_x = element_text(rotation=45, hjust=1),
plot_title = element_text(size=14, margin={'b':10})
)
)Plotting the global average from 2000 shows a rise from ~1.0 to ~4.5 births per 1,000 girls by 2004—then a powerful decline to under 1.0 by 2023. Yet the pale ribbon of 2020–21 marks a pandemic-era plateau, when progress wavered under lockdowns and strained health systems.
Why it matters: The overall decline is a testament to global commitments—investment in girls’ education, reproductive health access, and poverty reduction. But the COVID-19 pause warns that crises can swiftly undo years of gains, underscoring the need for resilient services and adaptable outreach.
“Educate a girl, and you educate a nation.” Reducing adolescent birth rates isn’t just a matter of numbers—it’s about giving young women the power to choose their own futures. Our four-scene journey showed us where teen motherhood is most common, who is hardest hit, how national wealth and smart policies can help or hinder progress, and when global efforts have succeeded or stalled.
By focusing resources on the countries with the highest rates, investing in schools and health clinics, and building systems that withstand crises, we can keep more girls in the classroom and out of early motherhood. Every drop in the teen birth rate means more girls finishing their education, starting careers, and contributing to healthier, stronger communities.